//面向对象的写法
//行数、列数、雷的数量都是由用户传进来的
function Mine(tr,td,mineNum){
    this.tr = tr; //tr表示行数 tablerow
    this.td = td; //td表示列数
    this.mineNum = mineNum; //雷的数量
    this.squares = [];
    //存储所有方块的信息，是一个二维数组，按行与列的顺序排放的，存取都使用行列的形式

    this.tds = []; //存储所有的单元格的dom对象(二维数组)
    this.surplusMine = mineNum; //剩余雷数
    this.allRight = false; //右击标的小红旗是否全是雷
    this.parent = document.querySelector('.gamebox');


}
//生成n个不重复的数字
Mine.prototype.randomNum = function(){
    var square = new Array(this.tr*this.td); // 生成一个空数组，但是有长度，长度为格子的总数
    for(var i = 0;i < square.length;i++){
        square[i] = i;
    }
    square.sort(function(){
        return 0.5-Math.random();
        
    })
  
    return square.slice(0,this.mineNum); //square返回的是雷的位置

}

Mine.prototype.init = function(){
    var rn = this.randomNum(); //雷的位置
    var n = 0; //用来找到格子对应的索引
    // this.randomNum();
    for(var i = 0;i < this.tr;i++){
        this.squares[i] = [];
        for(var j = 0;j < this.td;j++){
            n++;
            // this.squares[i][j] = ;
            //取方块在数组里的数据要用行与列的方式去取，找方块周围的方块，要用坐标的方式去取，行列的形式与坐标的形式是刚好相反的
            if(rn.indexOf(n) != -1){
                this.squares[i][j] = {
                    type:"mine",
                    x:j,
                    y:i
                }
            }else{
                this.squares[i][j] = {
                    type:'number',
                    x:j,
                    y:i,
                    value:0
                }
            }
        }
    }
    // console.log(this.squares);
    //看到二维数组，记得for循环二次嵌套
    
    this.updateNum();
    this.createDom();
    
    this.parent.oncontextmenu = function(){
        return false;
    }
    //剩余雷数
    this.mineNumDom = document.querySelector('.mineNum');
    this.mineNumDom.innerHTML = this.surplusMine;
   
}

//创建表格
Mine.prototype.createDom = function(){
    var This = this;
    var table = document.createElement('table');

    for(var i = 0;i < this.tr; i++){
        var domTr = document.createElement('tr');
        this.tds[i] = [];
        for(var j = 0;j < this.td;j++){ //循环列
            var domTd = document.createElement('td');


            domTd.pos = [i,j]; //把格子对应的行与列存到格子身上，为了下面通过这个值去数组里取到对应的数据
            
            domTd.onmousedown = function(){
                This.play(event,this);
                //This指的是实例对象，this指的是点击的那个td
            }
            
            this.tds[i][j] = domTd; //把所有创建的td添加到数组中去
           
           
            domTr.appendChild(domTd);
            // if(this.squares[i][j].type == 'mine'){
            //     domTd.className = 'mine';
            // }else if(this.squares[i][j].type == "number"){
            //     domTd.innerText = this.squares[i][j].value;
            // }
        }
        table.appendChild(domTr);

    }
    this.parent.innerHTML = ""; //避免多次点击创建多个
    this.parent.appendChild(table);
}

//找格子周围的格子
Mine.prototype.getAround = function(square){
    var x = square.x;
    var y = square.y;
    var result = []; //把找到的格子的坐标返回（也是一个二维数组）
    /*
        x-1.y-1   x,y-1   x+1,y-1
        x-1,y     x,y     x+1,y
        x-1,y+1   x,y+1   x+1,y+1
    */
   for(var i = x-1;i <= x+1;i++){   //此处i表示列 j表示行
       for(var j = y-1;j <= y+1;j++){
            if(i < 0 || j < 0 || i > this.td-1 || j>this.tr-1 || (i == x && j == y) || this.squares[j][i].type == "mine"){
                //需要排除掉四个角落以外的位置和自己以及和周围是雷的位置
                continue;
            }

            result.push([j,i]); //要以行与列的形式返回出来，因为需要用这去取数组里的数据


       }
   }

    return result;

}

//更新所有的数字
Mine.prototype.updateNum = function(){
    for(var i = 0;i < this.tr;i++){
        for(var j = 0; j < this.td;j++){
            //只更新雷周围的数字
            if(this.squares[i][j].type == "number"){
                continue;
            }

            var num = this.getAround(this.squares[i][j]); // 获取到每一个雷周围显示数字的格子
            for(var k = 0;k < num.length;k++){

                this.squares[num[k][0]][num[k][1]].value+=1;
                
            }
            
        }
    }

}

Mine.prototype.play = function(ev,obj){
    var This = this;

    if(ev.which == 1 && obj.className != 'flag'){
        //后面的条件是为了限制用户标完小红旗后不能再左键点击

        //点击的左键
        var curSquare = this.squares[obj.pos[0]][obj.pos[1]];
        var cl = ['zero','one','two','three','four','five','six','seven','eight'];
        if(curSquare.type == "number"){
            //用户点到的是数字
            // console.log('你点到的是数字');
            obj.innerHTML = curSquare.value;
            obj.className = cl[curSquare.value];
    
            if(curSquare.value == 0){
                obj.innerHTML = ""; //如果数字为0就不显示
                // 1.显示自己
                // 2.找周围的格子，显示出来（如果周围的值不为0显示到此即可）
                // 3.如果周围值有为0 的，就继续找周围的格子，以此类推（递归）
              
                function getAllZero(square){
                    var around = This.getAround(square); // 找到周围的格子
                    for(var i = 0;i < around.length;i++){
                        var x = around[i][0]; //行
                        var y = around[i][1]; //列
    
                        This.tds[x][y].className = cl[This.squares[x][y].value];
                        if(This.squares[x][y].value == 0){
                            if(!This.tds[x][y].check){
                                //给对应的td添加一个属性，来看这个格子是否被找过，如果被找过，则为true
                                //下次就不会再找了
                                This.tds[x][y].check = true;
                                getAllZero(This.squares[x][y]);
                            }
                            
                        }else{
                            //如果以某个格子为中心找到的四周的格子不为0,那就把数字显示出来
                            This.tds[x][y].innerHTML = This.squares[x][y].value;
                        }
    
                    }
    
                }
                getAllZero(curSquare);
            }
    
        }else{
            //用户点到的是雷
            // console.log('你点到雷了！');
            alert('你点到雷了!')
            this.gameOver(obj);
        }
    }

    
   
    if(ev.which == 3){
        //点击的右键
        //如果右击的是已经点开的数字，就无法点击
        if(obj.className && obj.className!='flag'){
            return ;
        }
        obj.className = obj.className =='flag' ? '' : 'flag';
        //切换class
        if(this.squares[obj.pos[0]][obj.pos[1]].type == 'mine'){
            this.allRight = true; //此时用户标的小红旗背后都是雷

        }else{
            this.allRight = false;
        }
        if(obj.className == 'flag'){
            this.mineNumDom.innerHTML = --this.surplusMine;
        }else{
            this.mineNumDom.innerHTML = ++this.surplusMine;
        }
        if(this.surplusMine == 0){
            //剩余的雷数为0，表示用户已经标完小红旗，这时候需要判断游戏是成功还是结束
            if(this.allRight == true){
                //条件成立说明用户全部标对了
                alert('恭喜你，游戏通过！');
            }else{
                alert('游戏失败');
                this.gameOver();
            }
        }
        

    }
}

//游戏失败函数
Mine.prototype.gameOver = function(clickTd){
    //1.显示所有的雷
    //2.取消点击事件
    //3.给点中的那个雷标红
    for(var i = 0; i < this.tr; i++){
        for(var j = 0; j < this.td; j++){
            if(this.squares[i][j].type == 'mine'){
                this.tds[i][j].className = 'mine';    
            }
            this.tds[i][j].onmousedown = null;

        }
    }
    if(clickTd){
        clickTd.style.backgroundColor = '#f00';
    }
}

//添加button的功能
var btns = document.querySelectorAll('.level button');
var mine = null; //用来存储生成的实例
var ln = 0; //用来处理当前选中的状态
var arr = [[9,9,10],[16,16,40],[28,28,99]]; //不同级数的行列和雷数

for(let i = 0; i < btns.length - 1; i++){
    btns[i].onclick = function(){
        btns[ln].className = "";
        this.className = "active";

        mine = new Mine(...arr[i]);
        
        mine.init();

        ln = i;

    }
}

btns[0].onclick(); //起初时弄成初级

btns[3].onclick = function(){
    mine.init();           
    this.surplusMine = 10;
}

var mine = new Mine(9,9,10);
mine.init();

